package com.vhall.component.controller.interactive;

import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vhall.component.controller.interactive.facade.QuestionFacade;
import com.vhall.component.controller.room.facade.RoomInnerFacade;
import com.vhall.component.dao.interactive.RoomQuestionLkMapper;
import com.vhall.component.entity.interactive.entity.QuestionsEntity;
import com.vhall.component.entity.interactive.vo.*;
import com.vhall.component.entity.room.RoomQuestionLkEntity;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.framework.common.annotation.VhallComponent;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.annotation.TokenAuth;
import com.vhall.component.plugin.common.annotation.VssTokenAuth;
import com.vhall.component.plugin.common.constant.ConstStr;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.Token;
import com.vhall.component.plugin.common.support.TokenThreadLocal;
import com.vhall.component.plugin.common.support.VssToken;
import com.vhall.component.plugin.common.support.VssTokenThreadLocal;
import com.vhall.component.service.interactive.QuestionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author guoxin.wang
 * @date 2021-06-11 16:36
 */
@VhallComponent
public class QuestionController implements QuestionFacade {

    @Autowired
    private QuestionService questionService;

    @Autowired
    private RoomInnerFacade roomInnerFacade;

    @Autowired
    private RoomQuestionLkMapper roomQuestionLkMapper;

    @VssTokenAuth
    @Override
    public QuestionPage<QuestionListRspVO> lists(QuestionListReqVO req) {
        if (req.getPage() == null) {
            req.setPage(1);
        }
        if (req.getPageSize() == null) {
            req.setPageSize(20);
        }
        if (StringUtils.isBlank(req.getRoomId()) && null == req.getAccountId()) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        QuestionListQuery query = new QuestionListQuery();
        BeanUtils.copyProperties(req, query);
        return questionService.list(query);
    }

    @VssTokenAuth
    @Override
    public QuestionsEntityDTO create(QuestionCreateReqVO req) {
        if (req.getIsPublic() == null) {
            req.setIsPublic(1);
        }
        // 1. 参数校验
        // 2. token校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        // 校验一下参数里的account id和token里的account id是否相等。
        if (req.getAccountId() == null || !String.valueOf(req.getAccountId()).equals(String.valueOf(accountId))) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        QuestionsEntity questionsEntity = questionService.create(req);
        QuestionsEntityDTO result = new QuestionsEntityDTO();
        BeanUtils.copyProperties(questionsEntity, result);
        return result;
    }

    @Override
    public Boolean delete(QuestionDeleteReqVO req) {
        return questionService.delete(req);
    }

    @Override
    public List<QuestionSubmitInfoRspVo> submitInfo(QuestionSubmitInfoReqVo req) {
        return questionService.submitInfo(req.getRoomId(), req.getQuestionId());
    }

    @VssTokenAuth
    @Override
    public Boolean checkSurvey(QuestionCheckSurveyReqVo req) {
        // 1. 参数校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        return questionService.checkSurvey(accountId, req.getRoomId(), req.getQuestionId());
    }

    @VssTokenAuth
    @Override
    public Boolean answer(QuestionAnswerReqVo req) {
        // 1. 参数校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        // 校验未发布的问卷不允许回答。
        boolean flag = validWhetherPublish(req.getQuestionId());
        if (!flag) {
            throw new BusinessException(BizErrorCode.COMP_QUESTION_CAN_NOT_ANSWER);
        }
        return questionService.answer(accountId, req.getRoomId(), req.getQuestionId(), req.getAnswerId(), req.getExtend());
    }

    @TokenAuth(check = false)
    @Override
    public Boolean submitAnswer(QuestionVisitorAnswerReqVo req) {
        // 1. 参数校验
        Token account = TokenThreadLocal.getToken();
        // 校验未发布的问卷不允许回答。
        boolean flag = validWhetherPublish(req.getQuestionId());
        if (!flag) {
            throw new BusinessException(BizErrorCode.COMP_QUESTION_CAN_NOT_ANSWER);
        }
        return questionService.visitorAnswer(account == null ? 0 : account.getAccountId(), req.getRoomId(), req.getQuestionId(),
                req.getAnswerId(), req.getExtend(), req.getDeviceId());
    }

    @VssTokenAuth
    @Override
    public Boolean publish(QuestionPublishReqVo req) {
        // 1. 参数校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        return questionService.publish(accountId, req.getRoomId(), req.getQuestionId());
    }

    @VssTokenAuth
    @Override
    public QuestionsEntityDTO update(QuestionUpdateReqVo reqVo) {
        // 1. 参数校验
        RoomsEntityDTO roomInfo = roomInnerFacade.getRoomInfo(reqVo.getRoomId());
        if (roomInfo == null) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        QuestionsEntity questionsEntity = questionService.update(reqVo);
        QuestionsEntityDTO result = new QuestionsEntityDTO();
        BeanUtils.copyProperties(questionsEntity, result);
        return result;
    }

    @VssTokenAuth
    @Override
    public Boolean publishCancel(QuestionPublishReqVo req) {
        // 1. 参数校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        RoomsEntityDTO roomInfo = roomInnerFacade.getRoomInfo(req.getRoomId());
        if (roomInfo == null) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        return questionService.publishCancel(accountId, req.getRoomId(), req.getQuestionId());
    }

    @VssTokenAuth
    @Override
    public Boolean repush(QuestionPushReqVo req) {
        // 1. 参数校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        // 校验一下参数里的account id和token里的account id是否相等。
        if (req.getAccountId() == null || !String.valueOf(req.getAccountId()).equals(String.valueOf(accountId))) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        // 校验未发布的问卷不允许推屏。
        boolean flag = validWhetherPublish(req.getQuestionId());
        if (!flag) {
            throw new BusinessException(BizErrorCode.COMP_QUESTION_CAN_NOT_PUSH);
        }
        return questionService.repush(accountId, req.getRoomId(), req.getQuestionId());
    }

    @VssTokenAuth
    @Override
    public Boolean copy(QuestionCopyReqVo req) {
        // 1. 参数校验
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        if (req.getAccountId() == null || !String.valueOf(accountId).equals(String.valueOf(req.getAccountId()))) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        QuestionsEntity doc = questionService.copy(accountId, req.getRoomId(), req.getQuestionId());
        return doc != null;
    }

    @VssTokenAuth
    @Override
    public QuestionsEntityDTO info(QuestionInfoReqVo reqVo) {
        // 1. 参数校验
        if (reqVo.getQuestionId() == null && reqVo.getSourceId() == null) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        QuestionsEntity info = questionService.info(reqVo);
        QuestionsEntityDTO result = new QuestionsEntityDTO();
        if (info != null) {
            BeanUtils.copyProperties(info, result);
        }
        return result;
    }

    @VssTokenAuth
    @Override
    public Boolean unbindRoom(QuestionUnbindRoomReqVo reqVo) {
        // 1. 参数校验
        RoomsEntityDTO roomInfo = roomInnerFacade.getRoomInfo(reqVo.getRoomId());
        if (roomInfo == null) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        Integer unbindRoom = questionService.unbindRoom(reqVo.getQuestionId(), reqVo.getRoomId(), roomInfo.getAccountId());
        return unbindRoom != null;
    }

    @VssTokenAuth
    @Override
    public QuestionPage<QuestionListRspVO> watchList(QuestionListWatcherReqVO req) {
        if (req.getPage() == null) {
            req.setPage(1);
        }
        if (req.getPageSize() == null) {
            req.setPageSize(6);
        }
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null == accountId || !String.valueOf(accountId).equals(String.valueOf(req.getAnswerAccountId()))) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        QuestionListQuery query = new QuestionListQuery();
        BeanUtils.copyProperties(req, query);
        query.setAccountId(req.getAnswerAccountId());
        query.setPublish(1);
        return questionService.watcherList(query);
    }

    @Override
    public QuestionListStatRspVO<QuestionStatDTO> statisticsList(QuestionListStatReqVO req) {
        if (req.getPage() == null) {
            req.setPage(1);
        }
        if (req.getPageSize() == null) {
            req.setPageSize(10);
        }
        QuestionListQuery query = new QuestionListQuery();
        BeanUtils.copyProperties(req, query);
        return questionService.statList(query);
    }

    @VssTokenAuth
    @Override
    public QuestionNumRspVO getNum(QuestionNumReqVO req) {
        if (StringUtils.isBlank(req.getRoomId()) && null == req.getAccountId()) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        VssToken tokenInfo = VssTokenThreadLocal.getToken();
        Integer accountId = tokenInfo.getThirdPartyUserId();
        if (null != req.getAccountId() && !String.valueOf(accountId).equals(String.valueOf(req.getAccountId()))) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_USER);
        }
        if (!StringUtils.isNotEmpty(req.getBeginDate())) {
            LocalDate begin = LocalDate.parse(req.getBeginDate(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
            req.setBeginDate(begin.toString() + " " + ConstStr.TIME_ZERO);
        }
        if (!StringUtils.isNotEmpty(req.getEndDate())) {
            LocalDate end = LocalDate.parse(req.getEndDate(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
            req.setBeginDate(end.toString() + " " + ConstStr.TIME_FULL);
        }

        return questionService.statNum(req);
    }

    private boolean validWhetherPublish(Integer questionId) {
        boolean result = true;
        LambdaQueryWrapper<RoomQuestionLkEntity> whereOfRqle = Wrappers.lambdaQuery();
        whereOfRqle.eq(RoomQuestionLkEntity::getQuestionId, questionId);
        whereOfRqle.eq(RoomQuestionLkEntity::getPublish, 0);
        RoomQuestionLkEntity roomQuestionLkEntity = roomQuestionLkMapper.selectOne(whereOfRqle);
        if (null != roomQuestionLkEntity) {
            result = false;
        }
        return result;
    }
}
